package com.ikas.ai.server.module.condition.service;

import cn.hutool.core.date.StopWatch;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ikas.ai.consts.Consts;
import com.ikas.ai.consts.MachineAndWorkConditionConst;
import com.ikas.ai.server.common.UpdateWorkConditionFlowJsonUtil;
import com.ikas.ai.server.common.parser.JSONWorkFlowParser;
import com.ikas.ai.server.common.parser.model.StepDetailMetaData;
import com.ikas.ai.server.common.parser.model.StepMetaData;
import com.ikas.ai.server.common.parser.model.WorkFlowMetaData;
import com.ikas.ai.server.error.BusinessException;
import com.ikas.ai.server.module.InitRedis;
import com.ikas.ai.server.module.condition.dao.WorkConditionFlowDao;
import com.ikas.ai.server.module.condition.dao.WorkStationDao;
import com.ikas.ai.server.module.condition.dto.*;
import com.ikas.ai.server.module.condition.model.WorkConditionConfig;
import com.ikas.ai.server.module.condition.model.WorkConditionFlow;
import com.ikas.ai.server.module.condition.model.WorkConditionStep;
import com.ikas.ai.server.module.condition.model.WorkConditionStepDetail;
import com.ikas.ai.server.module.data.service.DataMeteService;
import com.ikas.ai.server.module.system.model.User;
import com.ikas.ai.utils.BeanUtils;
import com.ikas.ai.utils.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @Description: 工况流程Service
 * @Author: qi.yilai
 * @Date: 2023/4/13 10:04
 * @Version: 1.0.0
 **/
@Service
@Slf4j
public class WorkConditionFlowService extends ServiceImpl<WorkConditionFlowDao, WorkConditionFlow> {

    @Autowired
    private WorkConditionFlowService workConditionFlowService;

    @Autowired
    private WorkConditionStepService workConditionStepService;

    @Autowired
    private WorkConditionStepDetailService workConditionStepDetailService;

    @Autowired
    private DataMeteService dataMeteService;

    @Autowired
    private WorkConditionFlowDao workConditionFlowDao;
    @Autowired
    private WorkStationDao workStationDao;

    @Autowired
    private InitRedis initRedis;

    private static final String REMOVE_STEP = "backStep0";

    /**
     * 获取工况模板
     *
     * @param wfName
     * @return
     */
    public WorkConditionFlowDTO findWorkConditionFlowConfiguration(String machineNo, String wfName) {
        LambdaQueryWrapper<WorkConditionFlow> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(WorkConditionFlow::getMachineNo, machineNo);
        lambdaQueryWrapper.eq(WorkConditionFlow::getWfName, wfName);
        //启用的流程才触发工况流程
        lambdaQueryWrapper.eq(WorkConditionFlow::getState, 1);
        WorkConditionFlow workConditionFlow = baseMapper.selectOne(lambdaQueryWrapper);
        if (Objects.isNull(workConditionFlow)) {
            throw new BusinessException(String.format(Locale.ENGLISH, "%s不存在启用的工况流程配置", wfName));
        }
        WorkConditionFlowDTO workConditionFlowDTO = BeanUtils.convert(workConditionFlow, WorkConditionFlowDTO.class);
        List<WorkConditionStep> steps = workConditionStepService.getWorkConditionStepByWfId(workConditionFlow.getId());
        if (CollectionUtil.isEmpty(steps)) {
            throw new BusinessException(String.format(Locale.ENGLISH, "%s工况步骤为空", wfName));
        }
        List<WorkConditionStepDTO> stepDTOS = BeanUtils.convert(steps, WorkConditionStepDTO.class);
        List<Long> stepIds = steps.stream().map(WorkConditionStep::getId).collect(Collectors.toList());
        Map<Long, List<WorkConditionStepDetail>> stepDetailMap = workConditionStepDetailService.getWorkConditionStepDetailByStepIds(stepIds).stream().collect(Collectors.groupingBy(WorkConditionStepDetail::getStepId));
        if (CollectionUtil.isEmpty(stepDetailMap)) {
            throw new BusinessException(String.format(Locale.ENGLISH, "%s工况步骤详情为空", wfName));
        }

        stepDTOS.stream().forEach(stepDto -> {
            List<WorkConditionStepDetail> list = stepDetailMap.get(stepDto.getId());
            if (!CollectionUtil.isEmpty(list)) {
                List<WorkConditionStepDetailDTO> details = Lists.newArrayList();
                list.forEach(workConditionStepDetail -> {
                    WorkConditionStepDetailDTO workConditionStepDetailDTO = BeanUtils.convert(workConditionStepDetail, WorkConditionStepDetailDTO.class);
                    // BeanUtils 无法转换
                    workConditionStepDetailDTO.setStepName(stepDto.getStepName());
                    workConditionStepDetailDTO.setPMeteCode(workConditionStepDetail.getPMeteCode());
                    workConditionStepDetailDTO.setDetailId(workConditionStepDetailDTO.getId());
                    details.add(workConditionStepDetailDTO);
                });

                stepDto.setDetails(details);
            }
        });

        workConditionFlowDTO.setSteps(stepDTOS);
        return workConditionFlowDTO;
    }

    /**
     * 删除指定的工况
     *
     * @param wfName
     * @return
     */
    public WorkConditionFlow removeWorkConditionFlow(String machineNo, String wfName) {
        LambdaQueryWrapper<WorkConditionFlow> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(WorkConditionFlow::getMachineNo, machineNo);
        lambdaQueryWrapper.eq(WorkConditionFlow::getWfName, wfName);
        WorkConditionFlow workConditionFlow = baseMapper.selectOne(lambdaQueryWrapper);
        baseMapper.delete(lambdaQueryWrapper);
        return workConditionFlow;
    }

    /**
     * 根据机组编号，工况流程名字获取步骤详情
     *
     * @param machineNO
     * @param wfName
     * @return
     */
    public List<WorkConditionStep> getStepsByWfName(String machineNO, String wfName) {
        WorkConditionFlow one = workConditionFlowService.getOne(
                new LambdaQueryWrapper<WorkConditionFlow>().eq(WorkConditionFlow::getWfName, wfName).eq(WorkConditionFlow::getMachineNo, machineNO)
        );
        return workConditionStepService.list(
                new LambdaQueryWrapper<WorkConditionStep>().eq(WorkConditionStep::getWfId, one.getId())
        );
    }

    public List<WorkConditionConfig> stationPage(String machineNo, String stationNo) {
        LambdaQueryChainWrapper<WorkConditionConfig> wrapper = new LambdaQueryChainWrapper<>(workStationDao);
        if (StringUtils.isNotEmpty(machineNo)) {
            switch (machineNo) {
                case MachineAndWorkConditionConst.MACHINE_01_NAME:
                    machineNo = MachineAndWorkConditionConst.MACHINE_01_NO;
                    break;
                case MachineAndWorkConditionConst.MACHINE_01_ALIAS:
                    machineNo = MachineAndWorkConditionConst.MACHINE_01_NO;
                    break;
                case MachineAndWorkConditionConst.MACHINE_02_NAME:
                    machineNo = MachineAndWorkConditionConst.MACHINE_02_NO;
                    break;
                case MachineAndWorkConditionConst.MACHINE_02_ALIAS:
                    machineNo = MachineAndWorkConditionConst.MACHINE_02_NO;
                    break;
                case MachineAndWorkConditionConst.MACHINE_03_NAME:
                    machineNo = MachineAndWorkConditionConst.MACHINE_03_NO;
                    break;
                case MachineAndWorkConditionConst.MACHINE_03_ALIAS:
                    machineNo = MachineAndWorkConditionConst.MACHINE_03_NO;
                    break;
                case MachineAndWorkConditionConst.MACHINE_04_NAME:
                    machineNo = MachineAndWorkConditionConst.MACHINE_04_NO;
                    break;
                case MachineAndWorkConditionConst.MACHINE_04_ALIAS:
                    machineNo = MachineAndWorkConditionConst.MACHINE_04_NO;
                    break;
            }
        }
        List<WorkConditionConfig> stationList =
                wrapper.like(StringUtils.isNotEmpty(machineNo), WorkConditionConfig::getMachineNo, machineNo)
                        .eq(StringUtils.isNotEmpty(stationNo), WorkConditionConfig::getStationNo, stationNo)
                        .list();
        List<WorkConditionFlow> list = list();
        //根据机组分组
        Map<String, List<WorkConditionFlow>> map = list.stream().collect(Collectors.groupingBy(WorkConditionFlow::getMachineNo));
        stationList.forEach(i -> {
            List<WorkConditionFlow> conditionFlowList = map.get(i.getMachineNo());
            if (CollectionUtils.isEmpty(conditionFlowList)) {
                i.setCompleteNum(0);
                i.setInCompleteNum(0);
            } else {
                List<WorkConditionFlow> flowList = conditionFlowList.stream().filter(c1 -> c1.getInfoConfigState() != null && c1.getFlowConfigState() != null).filter(c -> 1 == c.getInfoConfigState() && 1 == c.getFlowConfigState()).collect(Collectors.toList());
                int completeNum = 0;
                if (!CollectionUtil.isEmpty(flowList)) {
                    completeNum = flowList.size();
                }
                i.setCompleteNum(completeNum);
                i.setInCompleteNum(conditionFlowList.size() - completeNum);
                i.setTotalNum(conditionFlowList.size());
            }
        });
        stationList.forEach(i -> {
            String iMachineNo = i.getMachineNo();
            switch (iMachineNo) {
                case MachineAndWorkConditionConst.MACHINE_01_NO:
                    iMachineNo = MachineAndWorkConditionConst.MACHINE_01_ALIAS;
                    break;
                case MachineAndWorkConditionConst.MACHINE_02_NO:
                    iMachineNo = MachineAndWorkConditionConst.MACHINE_02_ALIAS;
                    break;
                case MachineAndWorkConditionConst.MACHINE_03_NO:
                    iMachineNo = MachineAndWorkConditionConst.MACHINE_03_ALIAS;
                    break;
                case MachineAndWorkConditionConst.MACHINE_04_NO:
                    iMachineNo = MachineAndWorkConditionConst.MACHINE_04_ALIAS;
                    break;
            }
            i.setMachineNo(iMachineNo);
        });
        return stationList;
    }

    public List<WorkConditionFlow> getPage(String machineNo) {
        LambdaQueryChainWrapper<WorkConditionFlow> wrapper = new LambdaQueryChainWrapper<>(workConditionFlowDao);
        return wrapper.eq(WorkConditionFlow::getMachineNo, machineNo)
                .list();
    }

    public void infoConfig(WorkConditionConfigDTO workConditionConfigDTO) {
        Long id = workConditionConfigDTO.getId();
        WorkConditionFlow workConditionFlow = workConditionFlowDao.selectById(id);
        if (Objects.isNull(workConditionFlow)) {
            throw new BusinessException("不存在该工况流程配置！");
        }
        if (Objects.nonNull(workConditionFlow.getState()) && 1 == workConditionFlow.getState()) {
            throw new BusinessException("请先禁用在进行编辑！");
        }
        workConditionFlow = BeanUtils.convert(workConditionConfigDTO, WorkConditionFlow.class);
//        workConditionFlow.setWfDesc(String.format("%s(%s->%s)", workConditionFlow.getWfName(), Objects.isNull(workConditionFlow.getCurrWc()) ? "" : workConditionFlow.getCurrWc(), Objects.isNull(workConditionFlow.getNextWc()) ? "" : workConditionFlow.getNextWc()));
        workConditionFlow.setUpdateTime(new Date());
        workConditionFlow.setInfoConfigState(1);
        updateById(workConditionFlow);
    }

    public List<WorkConditionConfig> stationList() {
        List<WorkConditionConfig> workConditionConfigs = workStationDao.selectList(null);
        return workConditionConfigs.stream().filter(distinctByVariable(WorkConditionConfig::getStationNo)).collect(Collectors.toList());
    }

    private static <T> Predicate<T> distinctByVariable(Function<? super T, ?> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    public void addStation(WorkStationAddDTO workStationAddDTO, User user) {
        LambdaQueryChainWrapper<WorkConditionConfig> wrapper = new LambdaQueryChainWrapper<>(workStationDao);
        List<WorkConditionConfig> stationList = wrapper.eq(WorkConditionConfig::getStationNo, workStationAddDTO.getStationNo())
                .eq(WorkConditionConfig::getMachineNo, workStationAddDTO.getMachineNo())
                .list();
        if (!CollectionUtil.isEmpty(stationList)) {
            throw new BusinessException("该电厂已存在相同机组！");
        }
        WorkConditionConfig workConditionConfig = BeanUtils.convert(workStationAddDTO, WorkConditionConfig.class);
        workConditionConfig.setStationName(Consts.STATION_NO.equals(workConditionConfig.getStationNo()) ? Consts.STATION_NAME : workConditionConfig.getStationName());
        workConditionConfig.setCreator(user.getId());
        workConditionConfig.setUpdater(user.getId());
        workConditionConfig.setCreateTime(new Date());
        workConditionConfig.setUpdateTime(new Date());
        workStationDao.insert(workConditionConfig);
    }

    public void updateStation(WorkStationUpdateDTO workStationUpdateDTO, User user) {
        LambdaQueryChainWrapper<WorkConditionConfig> wrapper = new LambdaQueryChainWrapper<>(workStationDao);
        List<WorkConditionConfig> stationList = wrapper.eq(WorkConditionConfig::getStationNo, workStationUpdateDTO.getStationNo())
                .eq(WorkConditionConfig::getMachineNo, workStationUpdateDTO.getMachineNo())
                .list();
        if (!CollectionUtil.isEmpty(stationList) && !stationList.get(0).getStationNo().equals(workStationUpdateDTO.getStationNo())) {
            throw new BusinessException("该电厂已存在相同机组！");
        }
        WorkConditionConfig workConditionConfig = BeanUtils.convert(workStationUpdateDTO, WorkConditionConfig.class);
        workConditionConfig.setStationName(Consts.STATION_NO.equals(workConditionConfig.getStationNo()) ? Consts.STATION_NAME : workConditionConfig.getStationName());
        workConditionConfig.setUpdater(user.getId());
        workConditionConfig.setUpdateTime(new Date());
        workStationDao.updateById(workConditionConfig);
    }

    public void deleteStation(List<Long> ids, User user) {
        log.info("用户:{}---删除厂站：{}", user.getUserName(), JSON.toJSONString(ids));
        workStationDao.deleteBatchIds(ids);
    }

    public void state(Long id, Integer state) {
        WorkConditionFlow workConditionFlow = workConditionFlowDao.selectById(id);
        if (Objects.isNull(workConditionFlow)) {
            throw new BusinessException("不存在该工况流程配置！");
        }
        workConditionFlow.setState(state);
        workConditionFlow.setUpdateTime(new Date());
        updateById(workConditionFlow);
    }

    @Transactional(rollbackFor = Exception.class)
    public void flowConfig(WorkConditionFlowConfigDTO workConditionFlowConfigDTO) {

        WorkConditionFlow workConditionFlow = workConditionFlowDao.selectById(workConditionFlowConfigDTO.getId());
        if (Objects.isNull(workConditionFlow)) {
            throw new BusinessException("该工况流程不存在！");
        }
        workConditionFlow.setConfig(workConditionFlowConfigDTO.getData());
        workConditionFlow.setFlowConfigState(1);
        workConditionFlow.setUpdateTime(new Date());
        updateById(workConditionFlow);
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        //删除工况流程步骤及步骤详情
        workConditionStepService.removeWorkConditionStepByWfId(workConditionFlowConfigDTO.getId());
        workConditionStepDetailService.removeWOrkConditionStepDetailByWfId(workConditionFlow.getId());
        initWorkConditionData(workConditionFlowConfigDTO, workConditionFlow);
        stopWatch.stop();
        log.info("condition三个表mysql执行时长：{}", stopWatch.getTotalTimeSeconds());
        stopWatch = new StopWatch();
        stopWatch.start();
        initRedis.initWorkFlowStartMeteCache();
        stopWatch.stop();
        log.info("START_WORKFLOW_STRING_KEY初始化redis执行时长：{}", stopWatch.getTotalTimeSeconds());
        //初始化t_data_mete
        dataMeteService.removeDataMeteByWfName(workConditionFlow.getMachineNo(), workConditionFlow.getWfName());
        stopWatch = new StopWatch();
        stopWatch.start();
        dataMeteService.initDataMeteService(workConditionFlow.getMachineNo(), workConditionFlow.getWfName());
        stopWatch.stop();
        log.info("initDataMeteService初始化redis执行时长：{}", stopWatch.getTotalTimeSeconds());
    }

    private void initWorkConditionData(WorkConditionFlowConfigDTO config, WorkConditionFlow workConditionFlow) {
        WorkFlowMetaData workFlowMetaData = JSONWorkFlowParser.parseData(config);
        List<StepMetaData> stepMetas = workFlowMetaData.getStepMetaData();

        List<WorkConditionStep> allSteps = Lists.newArrayList();
        List<WorkConditionStepDetail> details = Lists.newArrayList();
        stepMetas.removeIf(item -> REMOVE_STEP.equals(item.getStep()));
        stepMetas.forEach(stepMetaData -> {
            //校验步骤参数
            validStepData(stepMetaData);
            WorkConditionStep workConditionStep = createWorkConditionStep(workConditionFlow, stepMetaData);
            workConditionStepService.save(workConditionStep);
            allSteps.add(workConditionStep);
            List<StepDetailMetaData> list = stepMetaData.getDetails();
            Map<StepDetailMetaData, WorkConditionStepDetail> detailMap = createWorkConditionStepDetail(workConditionStep, list);
            details.addAll(detailMap.values());
            updateWorkConditionStepDetail(detailMap, list);
        });
        // 更新groupStepId
        updateGroupStepId(allSteps, details);
    }

    /**
     * 将json的更新策略修改为2，第一步缓存修改为1
     * 查询flow表里面的json
     * 将json中的数据进行修改，并再次保存；
     */
    public void initConfig() {
        LambdaQueryChainWrapper<WorkConditionFlow> wrapper = new LambdaQueryChainWrapper<>(workConditionFlowDao);
        List<WorkConditionFlow> list = wrapper.list();
    }

    private void validStepData(StepMetaData stepMetaData) {
        if (StringUtils.isBlank(stepMetaData.getStep())) {
            throw new BusinessException("from_step不能为空");
        }
        if (StringUtils.isBlank(stepMetaData.getMeteCode())) {
            throw new BusinessException(String.format("%s的mete_code不能为空", stepMetaData.getStep()));
        }
        if (StringUtils.isBlank(stepMetaData.getMeteName())) {
            throw new BusinessException(String.format("%s的mete_name不能为空", stepMetaData.getStep()));
        }
        if (Objects.isNull(stepMetaData.getType())) {
            throw new BusinessException(String.format("%s的type不能为空", stepMetaData.getStep()));
        }
    }

    /**
     * 创建工况流程步骤
     *
     * @param stepMetaData
     * @return
     */
    private WorkConditionStep createWorkConditionStep(WorkConditionFlow workConditionFlow, StepMetaData stepMetaData) {
        WorkConditionStep workConditionStep = new WorkConditionStep();
        workConditionStep.setWfId(workConditionFlow.getId());
        workConditionStep.setWfName(workConditionFlow.getWfName());
        workConditionStep.setStepName(stepMetaData.getStep());
        workConditionStep.setStep(Integer.parseInt(stepMetaData.getStep().substring(4)));
        workConditionStep.setMeteName(stepMetaData.getMeteName());
        workConditionStep.setMeteCode(stepMetaData.getMeteCode());
        workConditionStep.setValidMeteValue(stepMetaData.getValidMeteValue());
        workConditionStep.setDefaultDelay(stepMetaData.getDefaultDelay());
        workConditionStep.setSort(stepMetaData.getSort());
        workConditionStep.setType(stepMetaData.getType());
        workConditionStep.setCreateTime(new Date());
        return workConditionStep;
    }

    /**
     * 创建工况详情
     *
     * @param workConditionStep
     * @param list
     * @return
     */
    private Map<StepDetailMetaData, WorkConditionStepDetail> createWorkConditionStepDetail(WorkConditionStep workConditionStep, List<StepDetailMetaData> list) {
        Map<StepDetailMetaData, WorkConditionStepDetail> meta2DetailMap = Maps.newIdentityHashMap();
        List<WorkConditionStepDetail> details = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(list)) {
            list.stream().forEach(stepDetailMetaData -> {
                WorkConditionStepDetail workConditionStepDetail = new WorkConditionStepDetail();
                // 1= 测点 4=忽略项
                if (stepDetailMetaData.getLabelType() == 1 || stepDetailMetaData.getLabelType() == 4) {
                    workConditionStepDetail.setWfId(workConditionStep.getWfId());
                    workConditionStepDetail.setStepId(workConditionStep.getId());
                    if (StringUtils.isNotBlank(stepDetailMetaData.getMeteName())) {
                        workConditionStepDetail.setMeteName(stepDetailMetaData.getMeteName());
                    } else {
                        workConditionStepDetail.setMeteName(stepDetailMetaData.getLabel());
                    }
                    workConditionStepDetail.setLabel(stepDetailMetaData.getLabel());
                    workConditionStepDetail.setMeteCode(stepDetailMetaData.getMeteCode());
                    workConditionStepDetail.setValidMeteValue(stepDetailMetaData.getValidMeteValue());
                    workConditionStepDetail.setType(stepDetailMetaData.getType());
                    workConditionStepDetail.setLeaf(stepDetailMetaData.isLeaf());
                    workConditionStepDetail.setSubLogicalOperator(stepDetailMetaData.getSubLogicalOperator());
                    workConditionStepDetail.setSort(stepDetailMetaData.getSort());
                    workConditionStepDetail.setGroupNo(stepDetailMetaData.getGroupNo());
                    workConditionStepDetail.setGroupStep(stepDetailMetaData.getGroupToStep());
                    workConditionStepDetail.setLabelType(stepDetailMetaData.getLabelType());
                    workConditionStepDetail.setPMeteCode(stepDetailMetaData.getPMeteCodes());
                    workConditionStepDetail.setUpdatePolicy(stepDetailMetaData.getUpdatePolicy());
//                    if (("step0".equals(workConditionStep.getStepName()) || "step1".equals(workConditionStep.getStepName()))) {
//                        workConditionStepDetail.setEarlyCache(1);
//                    } else {
//                        workConditionStepDetail.setEarlyCache(stepDetailMetaData.getEarlyCache());
//                    }
                    workConditionStepDetail.setEarlyCache(stepDetailMetaData.getEarlyCache());
                    if (!stepDetailMetaData.isLeaf()) {
                        meta2DetailMap.putAll(createWorkConditionStepDetail(workConditionStep, stepDetailMetaData.getSubDetails()));
                    }
                    meta2DetailMap.put(stepDetailMetaData, workConditionStepDetail);
                } else if (stepDetailMetaData.getLabelType() == 2 || stepDetailMetaData.getLabelType() == 3) {
                    // 2=无测点,仅描述,3=无测点,虚线框
                    workConditionStepDetail.setWfId(workConditionStep.getWfId());
                    workConditionStepDetail.setStepId(workConditionStep.getId());
                    workConditionStepDetail.setType(stepDetailMetaData.getType());
                    workConditionStepDetail.setLabelType(stepDetailMetaData.getLabelType());
                    workConditionStepDetail.setLabel(stepDetailMetaData.getLabel());
                    workConditionStepDetail.setGroupNo(stepDetailMetaData.getGroupNo());
                    workConditionStepDetail.setGroupStep(stepDetailMetaData.getGroupToStep());
                    workConditionStepDetail.setUpdatePolicy(stepDetailMetaData.getUpdatePolicy());
                    workConditionStepDetail.setEarlyCache(stepDetailMetaData.getEarlyCache());
                    meta2DetailMap.put(stepDetailMetaData, workConditionStepDetail);
                }
                details.add(workConditionStepDetail);
            });
            validStepDetail(details);
            workConditionStepDetailService.saveBatch(details);
        }
        return meta2DetailMap;
    }

    /**
     * 校验步骤详情测点
     *
     * @param details
     */
    public void validStepDetail(List<WorkConditionStepDetail> details) {
        details.forEach(workConditionStepDetail -> {
            if (workConditionStepDetail.getLeaf() != null
                    && workConditionStepDetail.getLeaf()
                    && workConditionStepDetail.getLabelType() == 1) {
                //如果是叶子节点并且是测点类型,判断meteCode是否为空
                if (StringUtils.isBlank(workConditionStepDetail.getMeteCode())) {
                    throw new BusinessException("mete_code不能为空");
                }
                if (StringUtils.isBlank(workConditionStepDetail.getMeteName())) {
                    throw new BusinessException("mete_name不能为空");
                }
            }
        });
    }

    /**
     * 更新工况subIds和pDetailId详情
     *
     * @param meta2DetailMap
     * @param list
     */
    private void updateWorkConditionStepDetail(Map<StepDetailMetaData, WorkConditionStepDetail> meta2DetailMap, List<StepDetailMetaData> list) {

        List<WorkConditionStepDetail> details = Lists.newArrayList();
        list.stream().forEach(stepDetailMetaData -> {
            if (!CollectionUtil.isEmpty(stepDetailMetaData.getSubDetails())) {
                WorkConditionStepDetail workConditionStepDetail = meta2DetailMap.get(stepDetailMetaData);
                List<StepDetailMetaData> subs = stepDetailMetaData.getSubDetails();
                List<Long> subIds = subs.stream().map(sub -> {
                    WorkConditionStepDetail subWorkConditionStepDetail = meta2DetailMap.get(sub);
                    return subWorkConditionStepDetail.getId();
                }).collect(Collectors.toList());
                workConditionStepDetail.setSubDetailIds(subIds);
                if (!details.contains(workConditionStepDetail)) {
                    details.add(workConditionStepDetail);
                }

                subs.stream().forEach(sub -> {
                    WorkConditionStepDetail subWorkConditionStepDetail = meta2DetailMap.get(sub);
                    subWorkConditionStepDetail.setPDetailId(workConditionStepDetail.getId());
                    if (!details.contains(subWorkConditionStepDetail)) {
                        details.add(subWorkConditionStepDetail);
                    }
                });
                updateWorkConditionStepDetail(meta2DetailMap, subs);
            }
        });
        if (!details.isEmpty()) {
            workConditionStepDetailService.updateBatchById(details);
        }
    }

    /**
     * 更新groupStepId
     *
     * @param allSteps
     * @param details
     */
    private void updateGroupStepId(List<WorkConditionStep> allSteps, List<WorkConditionStepDetail> details) {
        Map<String, Long> key2IdMap = allSteps.stream().collect(Collectors.toMap(WorkConditionStep::getStepName, WorkConditionStep::getId));
        List<WorkConditionStepDetail> updates = Lists.newArrayList();

        details.stream().forEach(workConditionStepDetail -> {
            String toStep = workConditionStepDetail.getGroupStep();
            if (StringUtils.isNotEmpty(toStep) && !"step0".equals(toStep)) {
                Long stepId = key2IdMap.get(toStep);
                if (Objects.nonNull(stepId)) {
                    workConditionStepDetail.setGroupStepId(stepId);
                    updates.add(workConditionStepDetail);
                }
            }
        });
        if (!CollectionUtil.isEmpty(updates)) {
            workConditionStepDetailService.updateBatchById(updates);
        }
    }

    public String flowConfigInfo(Long id) {
        WorkConditionFlow workConditionFlow = workConditionFlowDao.selectById(id);
        if (Objects.isNull(workConditionFlow)) {
            throw new BusinessException("该工况流程不存在！");
        }
        return workConditionFlow.getConfig();
    }

    public WorkConditionFlow detail(String machineNo, String wfName) {
        LambdaQueryChainWrapper<WorkConditionFlow> wrapper = new LambdaQueryChainWrapper<>(workConditionFlowDao);
        return wrapper.eq(WorkConditionFlow::getMachineNo, machineNo)
                .eq(WorkConditionFlow::getWfName, wfName)
                .one();
    }

    /**
     * 更新flow的json ，step 0 和1 的earlyCache更新为1，其余步骤更新为0；所有的updatePolicy更新为2
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateWorkConditionFlowJson(Long id) throws JsonProcessingException {
        List<WorkConditionFlow> list;
        if (Objects.isNull(id)) {
            list = workConditionFlowService.list();
        } else {
            WorkConditionFlow workConditionFlow = workConditionFlowDao.selectById(id);
            list = Lists.newArrayList(workConditionFlow);
        }
        for (WorkConditionFlow workConditionFlow : list) {
            String newConfig = UpdateWorkConditionFlowJsonUtil.updateWorkConditionFlowJson(workConditionFlow.getConfig(), 2, 1, 0);
            //得到新的config，调用保存方法
            WorkConditionFlowConfigDTO workConditionFlowConfigDTO = new WorkConditionFlowConfigDTO();
            workConditionFlowConfigDTO.setId(workConditionFlow.getId());
            workConditionFlowConfigDTO.setData(newConfig);
            flowConfig(workConditionFlowConfigDTO);
        }
    }
}
